﻿using System.IO;
using LiteDB;
using SmartQuant;

namespace QuantBox
{
    public enum ObjectTableOwner
    {
        Order,Stop
    }

    public delegate void ObjectTableReader(ObjectTableOwner owner, ObjectTable table, BinaryReader writer);
    public delegate void ObjectTableWriter(ObjectTableOwner owner, ObjectTable table, BinaryWriter writer);

    internal class PositionSerializer
    {
        public static BsonDocument ToBson(PositionRecord position)
        {
            var doc = new BsonDocument();
            doc["_id"] = position.Id;
            doc["strategy_name"] = position.StrategyName;
            doc["symbol"] = position.Symbol;
            doc["direction"] = position.Direction;
            doc["qty"] = position.Qty;
            doc["qty_today"] = position.QtyToday;
            doc["frozen_open"] = position.FrozenOpen;
            doc["unfrozen_open"] = position.UnfrozenOpen;
            doc["frozen_close"] = position.FrozenClose;
            doc["unfrozen_close"] = position.UnfrozenClose;
            doc["frozen_close_today"] = position.FrozenCloseToday;
            doc["unfrozen_close_today"] = position.UnfrozenCloseToday;
            doc["holding_cost"] = position.HoldingCost;
            doc["cum_cancel_count"] = position.CumCancelCount;
            return doc;
        }

        public static PositionRecord ToPosition(BsonValue value)
        {
            var doc = (BsonDocument)value;
            var position = new PositionRecord(
                doc["strategy_name"].AsString, 
                doc["symbol"].AsString,
                doc["direction"].AsString);
            position.Qty = doc["qty"].AsDouble;
            position.QtyToday = doc["qty_today"].AsDouble;
            position.FrozenOpen = doc["frozen_open"].AsDouble;
            position.UnfrozenOpen = doc["unfrozen_open"].AsDouble;
            position.FrozenClose = doc["frozen_close"].AsDouble;
            position.UnfrozenClose = doc["unfrozen_close"].AsDouble;
            position.FrozenCloseToday = doc["frozen_close_today"].AsDouble;
            position.UnfrozenCloseToday = doc["unfrozen_close_today"].AsDouble;
            position.HoldingCost = doc["holding_cost"].AsDouble;
            position.CumCancelCount = doc["cum_cancel_count"].AsInt32;
            return position;
        }
    }

    internal class DataEventMapper : BsonMapper
    {
        public DataEventMapper(ObjectTableWriter? fieldsWriter, ObjectTableReader? fieldsReader)
        {
            ReportSerializer = new ExecutionReportSerializer();
            CommandSerializer = new ExecutionCommandSerializer(fieldsWriter, fieldsReader);
            StopSerializer = new StopSerializer(fieldsWriter, fieldsReader);
            RegisterType(CommandSerializer.ToBson, CommandSerializer.ToCommand);
            RegisterType(ReportSerializer.ToBson, ReportSerializer.ToReport);
            RegisterType(StopSerializer.ToBson!, StopSerializer.ToStop);
            RegisterType(PortfolioSerializer.ToBson, PortfolioSerializer.ToPortfolio);
            RegisterType(PositionSerializer.ToBson, PositionSerializer.ToPosition);
        }

        public readonly StopSerializer StopSerializer;
        public readonly ExecutionReportSerializer ReportSerializer;
        public readonly ExecutionCommandSerializer CommandSerializer;
    }
}